#ifndef XLCOMM_NET_CONNECTOR_H_
#define XLCOMM_NET_CONNECTOR_H_

#include <atomic>
#include <functional>
#include <memory>

#include "xlcomm/net/detail/channel.h"
#include "xlcomm/net/event_loop.h"
#include "xlcomm/net/inet_address.h"
#include "xlcomm/noncopyable.h"

namespace xlcomm {
namespace net {

// 客户端主动发起连接
class Connector : noncopyable {
 public:
  using NewConnectionCallback = std::function<void(int sockfd)>;

  Connector(EventLoop* loop, const InetAddress& server_addr);
  ~Connector();

  // 启动（能在任何线程调用）
  void Start();
  // 重启（必须在loop线程调用）
  void Restart();
  // 停止（能在任何线程调用）
  void Stop();

  // 注册连接成功后的回调
  void set_new_connection_callback(const NewConnectionCallback& cb) {
    new_connection_callback_ = cb;
  }

  const InetAddress& server_addr() const { return server_addr_; }

 private:
  enum State { kDisconnected, kConnecting, kConnected };
  static const int kInitRetryDelayMs = 500;
  static const int kMaxRetryDelayMs = 30 * 1000;

  // 在loop线程启动
  void StartInLoop();
  // 在loop线程停止
  void StopInLoop();
  // 连接服务端
  void Connect();
  // 正在连接处理
  void Connecting(int sockfd);
  // 关闭重连
  void CloseAndRetry(int sockfd);
  // 处理channel_可写事件
  void HandleWrite();
  // 处理channel_出错事件
  void HandleError();
  // 移除并重置channel
  int RemoveAndResetChannel();
  // 重置channel
  void ResetChannel();
  // 状态转字符串
  const char* StateToString() const;

  EventLoop* loop_;
  InetAddress server_addr_;
  std::unique_ptr<Channel> channel_;
  NewConnectionCallback new_connection_callback_;
  State state_;
  std::atomic<bool> will_connect_;
  int retry_delay_ms_;
};

}  // namespace net
}  // namespace xlcomm

#endif  // XLCOMM_NET_CONNECTOR_H_